package utils

import (
	"net/url"
	"time"

	"github.com/goccy/go-json"
	"github.com/gofiber/fiber/v2"
)

func GetFiberAgent(
	requestUrl,
	method string, 
	headers,
	queryArgs map[string]string, 
	body []byte, 
	timeout int,
) *fiber.Agent {
	// 解决偶现“missing required Host header in request”问题
	u, err := url.Parse(requestUrl)
	if (err != nil) {
		panic(err)
	}

	agent := fiber.AcquireAgent().Reuse()
	agent.Host(u.Hostname())
	agent.JSONEncoder(JSONMarshal)
	agent.JSONDecoder(json.Unmarshal)
	agent.Timeout(time.Duration(timeout) * time.Millisecond)

	request := agent.Request()
	request.Header.SetMethod(method)
	request.SetRequestURI(requestUrl)
	request.SetBody(body)
	request.SetTimeout(time.Duration(timeout) * time.Millisecond)

	for k, v := range headers {
		request.Header.Set(k, v)
	}
	for k, v := range queryArgs {
		request.URI().QueryArgs().Add(k, v)
	}
	request.Header.SetHost(u.Hostname())

	return agent
}

func HttpGet(url string) (int, []byte, error) {
	return HttpRequest(url, fiber.MethodGet, nil, nil, nil, 2000)
}

func HttpPost(url string, body []byte) (int, []byte, error) {
	return HttpRequest(url, fiber.MethodPost, nil, nil, body, 2000)
}

func HttpRequest(
	url,
	method string, 
	headers,
	queryArgs map[string]string, 
	body []byte, 
	timeout int,
) (int, []byte, error) {
	agent := GetFiberAgent(url, method, headers, queryArgs, body, timeout)
	defer fiber.ReleaseAgent(agent)

	if err := agent.Parse(); err != nil {
		return 0, nil, err
	}
	if httpStatus, responseBody, errs := agent.Bytes(); len(errs) > 0 {
		return 0, nil, errs[0]
	} else {
		return httpStatus, responseBody, nil
	}
}
